/*****************************************************************
 * JavaScript.Lang
 * 
 * Lang fixes for javascript, provides some useful functions
 * for solving some of javasctipt flaws like shitty inheritance
 * and inacurate typeof.
 * 
 *****************************************************************/
 
/**
 * Source: http://joncom.be/code/realtypeof/
 * @author Jon Combe - http://joncom.be/
 */
function TypeOf(v) {
    if (typeof(v) == "object") {
        if (v === null) return "null";
        if (v.constructor == (new Array).constructor) return "array";
        if (v.constructor == (new Date).constructor) return "date";
        if (v.constructor == (new RegExp).constructor) return "regex";
        return "object";
    }
    return typeof(v);
}

/**
 * Source: http://joncom.be/code/javascript-json-formatter/
 * @author Jon Combe - http://joncom.be/
 * 
 * @param oData mixed Any object or string.
 * @param sIndent optional, the current indentation.
 */
function FormatJSON(oData, sIndent) {
    if (arguments.length < 2) {
        sIndent = "";
    }
    var sIndentStyle = "    ";
    var sDataType = TypeOf(oData);
    var sHTML = "";
    var iCount = 0;

    // open object
    if (sDataType == "array") {
        if (oData.length == 0) {
            return "[]";
        }
        sHTML = "[";
    } else {
        iCount = 0;
        jQuery.each(oData, function() {
            iCount++;
            return;
        });
        if (iCount == 0) { // object is empty
            return "{}";
        }
        sHTML = "{";
    }

    // loop through items
    iCount = 0;
    jQuery.each(oData, function(sKey, vValue) {
        if (iCount > 0) {
            sHTML += ",";
        }
        if (sDataType == "array") {
            sHTML += ("\n" + sIndent + sIndentStyle);
        } else {
            sHTML += ("\n" + sIndent + sIndentStyle + "\"" + sKey + "\"" + ": ");
        }

        // display relevant data type
        switch (TypeOf(vValue)) {
            case "array":
            case "object":
                sHTML += FormatJSON(vValue, (sIndent + sIndentStyle));
                break;
            case "boolean":
            case "number":
                sHTML += vValue.toString();
                break;
            case "null":
                sHTML += "null";
                break;
            case "string":
                sHTML += ("\"" + vValue + "\"");
                break;
            default:
                sHTML += ("TYPEOF: " + typeof(vValue));
        }

        // loop
        iCount++;
    });

    // close object
    if (sDataType == "array") {
        sHTML += ("\n" + sIndent + "]");
    } else {
        sHTML += ("\n" + sIndent + "}");
    }

    // return
    return sHTML;
}


//From jo Framework
// syntactic sugar to make it easier to extend a class
/**
 * How to Use:
 * 
 * Create a parent class:
 * 
 * MyParentClass = function(){
 *      this.nonInheritableAttributes;
 * }
 * MyParentClass.prototype = {
 *      myOverridableFunction:function(){
 *          alert("Wiiiiii");
 *      }
 * }
 * 
 * Create a Child class
 * 
 * MyChildClass = function(){
 *      //Call parent constructor:
 *      MyParentClass.apply(this, arguments);
 *      this.otherNonInheritableAttributes;
 * }
 * MyClass.extend(MyParentClass, {
 *      //Overriding a function
 *      myOverridableFunction:function(){
 *          //Call parent's version of the function...
 *          this.parent.myOverridableFunction.call(this); //<-- ugly, but that's what is there.
 *          alert("And now presenting... Wiiiiii Uuuuuuuu");
 *      }
 * });
 * 
 */
Function.prototype.Extend = function(superclass, proto) {
    // create our new subclass
    this.prototype = new superclass();
    this.prototype.parent = superclass.prototype;

    // optional subclass methods and properties
    if (proto) {
        for (var i in proto)
            this.prototype[i] = proto[i];
    }
};
/**
 * Dynamically imports a script. This method ensures that any script
 * gets loaded twice.
 *
 * @param dir The name of a javascript file.
 */
function using(dir){
    var headElement = document.getElementsByTagName("head")[0];
        
    function scriptIsLoaded(dir){
        scripts = headElement.getElementsByTagName("script");
            
        for(var i in scripts){
            if(scripts[i].src == dir){
                return true;
            }
        }
            
        return false;
    }
        
    function doLoad(dir){
        var newScript = document.createElement('script');
        newScript.type = 'text/javascript';
        newScript.src = dir;
        headElement.appendChild(newScript);
    }
        
    if(!scriptIsLoaded(dir)){
        doLoad(dir);
    }
}

String.format = function() {
    var s = arguments[0];
    for (var i = 0; i < arguments.length - 1; i++) {       
        var reg = new RegExp("\\{" + i + "\\}", "gm");             
        s = s.replace(reg, arguments[i + 1]);
    }

    return s;
}